﻿using System;
using System.Diagnostics.Tracing;
using System.Threading;

namespace Sustainalytics.PregenerateScreeningReports.Service
{
    [EventSource(Name = "Sustainalytics-PregenerateScreeningReports")]
    public sealed class PSREventSource : System.Diagnostics.Tracing.EventSource
    {
        private static Lazy<PSREventSource> _lazyLog = new Lazy<PSREventSource>(InitLog, LazyThreadSafetyMode.ExecutionAndPublication);

        private PSREventSource()
        {
        }

        public static PSREventSource Log
        {
            get
            {
                return _lazyLog.Value;
            }
        }

        [NonEvent]
        private static PSREventSource InitLog()
        {
            var log = new PSREventSource();
            log.Ping();

            return log;
        }

        [Event(9001, Level = EventLevel.LogAlways)]
        public void Ping()
        {
            if (IsEnabled())
            {
                WriteEvent(9001);
            }
        }

        [Event(9002, Level = EventLevel.LogAlways, Message = "Process[{0}] enters, is user interactive {1}, arguments count: {2} ")]
        public void Enter(int id, bool isUserInteractiv, int countArgs)
        {
            if (IsEnabled())
            {
                WriteEvent(9002, id, isUserInteractiv, countArgs);
            }
        }

        [Event(9003, Level = EventLevel.LogAlways, Message = "Machine shutdown sheduled to {0}")]
        public void ShutdownScheduledOn(string s)
        {
            if (IsEnabled())
            {
                WriteEvent(9003, s);
            }
        }

        [Event(9004, Level = EventLevel.LogAlways, Message = "Machine shutdown now!")]
        public void Shutdown()
        {
            if (IsEnabled())
            {
                WriteEvent(9004);
            }
        }

        [Event(9005, Level = EventLevel.LogAlways, Message = "Process[{0}] exits")]
        public void Exit(int id)
        {
            if (IsEnabled())
            {
                WriteEvent(9005, id);
            }
        }

        [Event(9006, Level = EventLevel.LogAlways, Message = "Process[{0}] as service: {1} , with arguments {2} ")]
        public void Start(bool isUserInteractive, int id, string arguments)
        {
            if (IsEnabled())
            {
                WriteEvent(9006, id, !isUserInteractive, arguments);
            }
        }

        [Event(9007, Level = EventLevel.LogAlways, Message = "Process[{0}] received stop command")]
        public void Stop(int id)
        {
            if (IsEnabled())
            {
                WriteEvent(9007, id);
            }
        }

        [Event(9008, Level = EventLevel.LogAlways, Message = "Orchestrator[{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}]")]
        public void Orchestrator(int id, string clientDWMasterCnx, string clientPlatformCnx, string instanceId, string redisServerAddress,
                        string esgComputationServiceAddress, string tempPath, int loadIndicator)
        {
            if (IsEnabled())
            {
                WriteEvent(9008, id, clientDWMasterCnx, clientPlatformCnx, instanceId, redisServerAddress,
                        esgComputationServiceAddress, tempPath, loadIndicator);
            }
        }

        [Event(9009, Level = EventLevel.LogAlways, Message = "Orchestrator[{0}|{1}]")]
        public void OrchestratorRunComplete(int id, string log)
        {
            if (IsEnabled())
            {
                WriteEvent(9009, id, log);
            }
        }

        [Event(9010, Level = EventLevel.LogAlways, Message = "WorkerProcess [{0}|{1}|{2}|{3}|{4}]")]
        public void WorkerProcess(int id, string fileName, string tempPath, string requestsIds, string clientDWMaster, string clientPlatform, string accountPosition)
        {
            if (IsEnabled())
            {
                WriteEvent(9010, id, fileName, tempPath, requestsIds, clientDWMaster, clientPlatform, accountPosition);
            }
        }

        [Event(9011, Level = EventLevel.LogAlways, Message = "WorkerProcess [{0}|{1}]")]
        public void WorkerProcessCompleted(int id, string log)
        {
            if (IsEnabled())
            {
                WriteEvent(9011, id, log);
            }
        }

        [NonEvent]
        public void Exception(Exception ex)
        {
            if (System.Environment.UserInteractive)
            {
                Console.WriteLine(ex.ToString());
            }
            if (ex != null)
                this.Exception(System.Diagnostics.Process.GetCurrentProcess().Id, ex.GetType().ToString(), ex.Message, ex.ToString());
        }

        [Event(9012, Level = EventLevel.Error, Message = "{0} found {1}:{2}")]
        public void Exception(int processId, string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            if (IsEnabled())
                WriteEvent(9012, processId, exceptionType, exceptionMessage, exceptionInformation);
        }

        [Event(9013, Level = EventLevel.Informational, Message = "Process {0} generated: {1}")]
        public void ReportStatus(int id, string log)
        {
            if (IsEnabled())
            {
                WriteEvent(9013, id, log);
            }
        }

        [Event(9014, Level = EventLevel.Warning, Message = "Process {0} Company Not Found In CIQIDDictionary: {1}")]
        public void CompanyNotFoundInCIQIDDictionary(int id, string companyid)
        {
            if (IsEnabled())
            {
                WriteEvent(9014, id, companyid);
            }
        }

        [NonEvent]
        public void Distribution(string log)
        {
            if (IsEnabled())
            {
                var id = System.Diagnostics.Process.GetCurrentProcess().Id;
                int size;
                do
                {
                    size = Math.Min(4096, log.Length);

                    this.Distribution(id, log.Substring(0, size));

                    if (log.Length > size)
                        log = log.Substring(size);
                }
                while (log.Length > size);
            }
        }

        [Event(9015, Level = EventLevel.LogAlways, Message = "Distribution[{0}|{1}]")]
        public void Distribution(int id, string log)
        {
            if (IsEnabled())
            {
                WriteEvent(9015, id, log);
            }
        }

        [Event(9016, Level = EventLevel.LogAlways, Message = "S3 folder to write to {0}")]
        public void S3Folder(string name)
        {
            if (IsEnabled())
            {
                WriteEvent(9016, name);
            }
        }
    }
}
